﻿namespace Home.Services
{
    using System;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Globalization;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web;
    using System.Web.Http.Controllers;
    using System.Web.Http.Filters;
    using Home.Models;
    using Home.Repository;
    using Home.Security;

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class RequestValidationAttribute : AuthorizationFilterAttribute, IAuthorizationFilter
    {
        public RequestType RequestType { get; set; }

        public override async Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
        {
            var ids = default(IEnumerable<string>);
            if (!actionContext.Request.Headers.TryGetValues("home-request-id", out ids) || ids.Count() != 1)
            {
                goto ERROR;
            }

            var id = ids.ElementAt(0);
            var date = default(DateTime);
            var guid = default(Guid);
            if (!SecurityHelper.TryParseRequestId(id, out date, out guid, out id))
            {
                goto ERROR;
            }

            var now = DateTime.UtcNow;
            var today = now.Date;
            if (date > today)
            {
                goto ERROR;
            }
            else if (date < today && now.Hour > 0 && now.Minute > 1)
            {
                goto ERROR;
            }

            using (var db = new UtilityDbContext())
            {
                if (await db.Requests.AnyAsync(u => u.Date == date && u.Guid == guid && u.Type == this.RequestType))
                {
                    goto ERROR;
                }

                var utc = DateTimeOffset.UtcNow;
                var user = Thread.CurrentPrincipal.Identity.Name;
                db.Requests.Add(new RequestDescription()
                {
                    Id = Guid.NewGuid(),
                    Date = date,
                    Guid = guid,
                    Type = this.RequestType,
                    Created = utc,
                    CreatedBy = user,
                    Modified = utc,
                    ModifiedBy = user,
                });
                await db.SaveChangesAsync();
            }

            return;

            ERROR:
            actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "The HTTP header home-request-id is either disappear or invalid.");
        }
    }
}